﻿using System;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using advadev.CanOpen;


namespace advadev.CanOpen.UnitTests
{

    /// <summary>
    /// Represents the time stamp object write transfer unit tests
    /// </summary>
    [TestClass]
    public class TimeStampObjectWriteTransferTest : ICanOpenObjectDictionaryContainer
    {

        #region constructor tests
        /// <summary>
        /// Constructor test
        /// </summary>
        [TestMethod]
        public void ConstructorTest()
        {
            // initialization
            UInt16 days = 0;
            uint milliseconds = 0;
            TimeStampObjectWriteTransfer testObject = null;

            // valid time stamp
            testObject = new TimeStampObjectWriteTransfer(days, milliseconds);
            Assert.IsNotNull(testObject);
        }
        #endregion constructor tests


        #region producer side tests
        /// <summary>
        /// Producer side test
        /// </summary>
        [TestMethod]
        public void ProducerSideTest()
        {
            // initialization
            UInt16 cobId = 0x200;
            UInt16 days = 0;
            uint milliseconds = 0;
            TimeStampObjectWriteTransfer testObject = null;

            // test with milliseconds 10000 and days 100
            days = 100;
            milliseconds = 10000;
            testObject = new TimeStampObjectWriteTransfer(days, milliseconds);
            testObject.Start();
            Assert.AreEqual(false, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(1, testObject.PendingSendMessages.Count);
            Assert.AreEqual(0x100, testObject.PendingSendMessages[0].CanId);
            Assert.AreEqual(0x64, testObject.PendingSendMessages[0].Byte0);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte1);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte2);
            Assert.AreEqual(0x71, testObject.PendingSendMessages[0].Byte3);
            Assert.AreEqual(0x02, testObject.PendingSendMessages[0].Byte4);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte5);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte6);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte7);
            Assert.AreEqual((uint)6, testObject.PendingSendMessages[0].Length);
            testObject.ContinueAfterSendingMessages();
            Assert.AreEqual(true, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(0, testObject.PendingSendMessages.Count);

            // test with changed COB-ID
            days = 100;
            milliseconds = 10000;
            testObject = new TimeStampObjectWriteTransfer(days, milliseconds, cobId);
            testObject.Start();
            Assert.AreEqual(false, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(1, testObject.PendingSendMessages.Count);
            Assert.AreEqual(cobId, testObject.PendingSendMessages[0].CanId);
            Assert.AreEqual(0x64, testObject.PendingSendMessages[0].Byte0);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte1);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte2);
            Assert.AreEqual(0x71, testObject.PendingSendMessages[0].Byte3);
            Assert.AreEqual(0x02, testObject.PendingSendMessages[0].Byte4);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte5);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte6);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte7);
            Assert.AreEqual((uint)6, testObject.PendingSendMessages[0].Length);
            testObject.ContinueAfterSendingMessages();
            Assert.AreEqual(true, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(0, testObject.PendingSendMessages.Count);
        }
        #endregion producer side tests


        #region is time stamp object write transfer request tests
        /// <summary>
        /// Is time stamp object write transfer request test
        /// </summary>
        [TestMethod]
        public void IsTimeStampObjectWriteTransferRequestTest()
        {
            // initialization
            bool isTimeStampObjectWriteTransferRequest = false;
            UInt16 cobId = 0x101;
            UInt16 receivedDays = 0;
            uint receivedMilliseconds = 0;
            TimeStampObjectReceivedEventHandler handler = new TimeStampObjectReceivedEventHandler((object sender, TimeStampObjectReceivedEventArgs args) =>
            {
                receivedDays = args.Days;
                receivedMilliseconds = args.Milliseconds;
            });
            TimeStampObjectWriteTransfer testObject = null;

            // test with valid received can open message
            isTimeStampObjectWriteTransferRequest = TimeStampObjectWriteTransfer.IsTimeStampObjectWriteTransfer(new CanOpenMessage(0x100, 0x64, 0x00, 0x00, 0x71, 0x02, 0x00, 0x00, 0x00), out testObject, handler);
            Assert.AreEqual(true, isTimeStampObjectWriteTransferRequest);
            Assert.IsNotNull(testObject);

            // test with wrong COB-ID
            isTimeStampObjectWriteTransferRequest = TimeStampObjectWriteTransfer.IsTimeStampObjectWriteTransfer(new CanOpenMessage(0x100, 0x64, 0x00, 0x00, 0x71, 0x02, 0x00, 0x00, 0x00), out testObject, cobId, handler);
            Assert.AreNotEqual(true, isTimeStampObjectWriteTransferRequest);
            Assert.IsNull(testObject);

            // test with handler is null
            isTimeStampObjectWriteTransferRequest = TimeStampObjectWriteTransfer.IsTimeStampObjectWriteTransfer(new CanOpenMessage(0x100, 0x64, 0x00, 0x00, 0x71, 0x02, 0x00, 0x00, 0x00), out testObject, null);
            Assert.AreEqual(true, isTimeStampObjectWriteTransferRequest);
            Assert.IsNotNull(testObject);
        }
        #endregion is time stamp object write transfer request tests


        #region consumer side tests
        /// <summary>
        /// Consumer side test
        /// </summary>
        [TestMethod]
        public void ComsumerSideTest()
        {
            // initialization
            bool isTimeStampObjectWriteTransferRequest = false;
            UInt16 cobId = 0x180;
            UInt16 receivedDays = 0;
            UInt16 days = 0;
            uint receivedMilliseconds = 0;
            uint milliseconds = 0;
            TimeStampObjectReceivedEventHandler handler = new TimeStampObjectReceivedEventHandler((object sender, TimeStampObjectReceivedEventArgs args) =>
            {
                receivedDays = args.Days;
                receivedMilliseconds = args.Milliseconds;
            });
            TimeStampObjectWriteTransfer testObject = null;
            TimeStampObjectWriteTransfer producerTransfer = null;

            // test with milliseconds 10000 and days 100
            receivedDays = 0;
            receivedMilliseconds = 0;
            days = 100;
            milliseconds = 10000;
            producerTransfer = new TimeStampObjectWriteTransfer(days, milliseconds);
            producerTransfer.Start();
            isTimeStampObjectWriteTransferRequest = TimeStampObjectWriteTransfer.IsTimeStampObjectWriteTransfer(producerTransfer.PendingSendMessages[0], out testObject, handler);
            Assert.AreEqual(true, isTimeStampObjectWriteTransferRequest);
            Assert.IsNotNull(testObject);
            testObject.Start();
            Assert.AreEqual(days, receivedDays);
            Assert.AreEqual(milliseconds, receivedMilliseconds);
            Assert.AreEqual(true, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(0, testObject.PendingSendMessages.Count);

            // test with changed COB-ID
            receivedDays = 0;
            receivedMilliseconds = 0;
            days = 100;
            milliseconds = 10000;
            producerTransfer = new TimeStampObjectWriteTransfer(days, milliseconds, cobId);
            producerTransfer.Start();
            isTimeStampObjectWriteTransferRequest = TimeStampObjectWriteTransfer.IsTimeStampObjectWriteTransfer(producerTransfer.PendingSendMessages[0], out testObject, cobId, handler);
            Assert.AreEqual(true, isTimeStampObjectWriteTransferRequest);
            Assert.IsNotNull(testObject);
            testObject.Start();
            Assert.AreEqual(days, receivedDays);
            Assert.AreEqual(milliseconds, receivedMilliseconds);
            Assert.AreEqual(true, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(0, testObject.PendingSendMessages.Count);

            // test without handler
            receivedDays = 0;
            receivedMilliseconds = 0;
            days = 100;
            milliseconds = 10000;
            producerTransfer = new TimeStampObjectWriteTransfer(days, milliseconds);
            producerTransfer.Start();
            isTimeStampObjectWriteTransferRequest = TimeStampObjectWriteTransfer.IsTimeStampObjectWriteTransfer(producerTransfer.PendingSendMessages[0], out testObject, null);
            Assert.AreEqual(true, isTimeStampObjectWriteTransferRequest);
            Assert.IsNotNull(testObject);
            testObject.Start();
            Assert.AreEqual((UInt16)0, receivedDays);
            Assert.AreEqual((uint)0, receivedMilliseconds);
            Assert.AreEqual(true, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(0, testObject.PendingSendMessages.Count);
        }
        #endregion consumer side tests


        #region ICanOpenObjectDictionaryContainer
        /// <summary>
        /// Gets the node id of the can open object dictionary container
        /// </summary>
        byte ICanOpenObjectDictionaryContainer.NodeId
        {
            get
            {
                return 103;
            }
        }

        /// <summary>
        /// Gets the can open object with the given index as can open data field
        /// object
        /// </summary>
        /// <param name="index">
        /// Index of the can open object to get
        /// </param>
        /// <returns>
        /// The can open object with the given index as data field object or
        /// null
        /// </returns>
        ICanOpenDataFieldObject ICanOpenObjectDictionaryContainer.GetCanOpenObject(UInt16 index)
        {
            return null;
        }

        /// <summary>
        /// Gets the can open object with the given index and sub index as can
        /// open value object
        /// </summary>
        /// <param name="index">
        /// Index of the can open object to get
        /// </param>
        /// <param name="subIndex">
        /// Sub index of the can open object to get
        /// </param>
        /// <returns>
        /// The can open object with the given index and sub index as value
        /// object or null
        /// </returns>
        ICanOpenValueObject ICanOpenObjectDictionaryContainer.GetCanOpenObject(UInt16 index, byte subIndex)
        {
            return null;
        }
        #endregion ICanOpenObjectDictionaryContainer

    }

}
